package pagerank;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;


public class PageCollection {

	private HashMap<String, Page> pagesMap;
	private ArrayList<Page> pages;
	private final double pagerankVar;
	private double nbrOfPages;

	public PageCollection(ArrayList<Page> pages, HashMap<String, Page> pagesMap) {
		this.pagesMap = pagesMap;
		this.pages = pages;
		removeNonExistingFlinks();
		nbrOfPages = pages.size();
		pagerankVar = (1 - Main.D)/nbrOfPages;
	}
	
	private void removeNonExistingFlinks(){
		int linksRemoved = 0;
		int fLinksInTotal = 0;
		for (Page page : pages) {
			if(!page.fLinks.isEmpty()){
				ArrayList<String> idsToRemove = new ArrayList<String>();
				for (String pageId : page.fLinks) {
					fLinksInTotal++;
					Page fLinkedPage = pagesMap.get(pageId);
					if(fLinkedPage == null){
						idsToRemove.add(pageId);
					}
				}
				for(String s : idsToRemove){
					page.fLinks.remove(s);
					linksRemoved++;
				}
			}
		}
		System.out.println("FLinks removed: " + linksRemoved);
		System.out.println("Total FLinks: " + fLinksInTotal);
		System.out.println();
	}

	public double iteratePagerank() {
		commitToNewPagerank();
		for (Page page : pages) {
			double pagerankValue;
			if(!page.fLinks.isEmpty()){
				pagerankValue = (page.oldPageRank) / ((double) page.fLinks.size());
				for (String pageId : page.fLinks) {
					Page fLinkedPage = pagesMap.get(pageId);
					fLinkedPage.newPageRank += pagerankValue;
				}
			} else {
				pagerankValue = (page.oldPageRank) / nbrOfPages;
				for (Page p : pages) {
					p.newPageRank += pagerankValue;
				}
			}
		}
		for (Page page : pages) {
			page.newPageRank = pagerankVar + Main.D * page.newPageRank;
		}
		
		double avgDiff = calcAvgDiffForIteration();
		return avgDiff;
	}
	
	private void commitToNewPagerank(){
		for (Page page : pages) {
			page.oldPageRank = page.newPageRank;
			page.newPageRank = 0;
		}
	}

	private double calcAvgDiffForIteration() {
		double diffSum = 0;
		for (Page page : pages) {
			diffSum += Math.abs(page.newPageRank - page.oldPageRank);
		}
		double diffAvg = diffSum / nbrOfPages;
		return diffAvg;
	}
	
	public ArrayList<Page> findNeighbours(ArrayList<String> links){
		ArrayList<Page> neighbours = new ArrayList<Page>();
		for(String link : links){
			if(pagesMap.containsKey(link)){
				neighbours.add(pagesMap.get(link));
			}
		}
		return neighbours;
	}
}
